package cn.net.autocode.maths;

import org.apache.commons.math3.stat.regression.RegressionResults;
import org.apache.commons.math3.stat.regression.SimpleRegression;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 直线回归，线性拟合，
 * 计算标准曲线的斜率、截距、相关系数等信息
 */
public class LinearRegression {

    /**
     * @param data 对照数组
     * @return 斜率、截距、相关系数数组
     */
    public static double[] execute(double[][] data){
        SimpleRegression regression = new SimpleRegression();
        regression.addData(data); // 数据集
        /*
         * RegressionResults 中是拟合的结果
         * 其中重要的几个参数如下：
         *   parameters:
         *      0: b 截距
         *      1: k 斜率
         *   globalFitInfo
         *      0: 平方误差之和, SSE
         *      1: 平方和, SST
         *      2: R 平方, RSQ
         *      3: 均方误差, MSE
         *      4: 调整后的 R 平方, adjRSQ
         *
         * */
        RegressionResults results = regression.regress();
        BigDecimal b = BigDecimal.valueOf(results.getParameterEstimate(0)).setScale(8, RoundingMode.HALF_UP);
        BigDecimal k = BigDecimal.valueOf(results.getParameterEstimate(1)).setScale(8,RoundingMode.HALF_UP);
        BigDecimal r = BigDecimal.valueOf(results.getRSquared()).setScale(8,RoundingMode.HALF_UP);
        StringBuilder func = new StringBuilder();
        func.append("f(x) =");

        func.append(k.compareTo(BigDecimal.valueOf(0))>=0 ? "" : " - ");
        func.append(k.abs());
        func.append("x");
        func.append(b.compareTo(BigDecimal.valueOf(0))>=0 ? "+" : " - ");
        func.append(b.abs());

        double[] rs = new double[3];
        rs[0] = k.doubleValue();
        rs[1] = b.doubleValue();
        rs[2] = r.doubleValue();

        return rs;
    }

    /*public static void main(String[] args){
        double[][] data = new double[6][2];
        data[0][0] = 0;
        data[0][1] = 0;

        data[1][0] = 5.04;
        data[1][1] = 0.152;

        data[2][0] = 10.08;
        data[2][1] = 0.311;

        data[3][0] = 15.12;
        data[3][1] = 0.463;

        data[4][0] = 20.16;
        data[4][1] = 0.610;

        data[5][0] = 25.20;
        data[5][1] = 0.769;
        LinearRegression.execute(data);
    }*/

}
